package test3.backtracking;

import java.util.ArrayList;
import java.util.List;

/**
 * 51. N 皇后
 * <p>
 * n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
 * <p>
 * 给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。
 * <p>
 * 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。
 * <p>
 * 提示：1 <= n <= 9   皇后彼此不能相互攻击，也就是说：任何两个皇后都不能处于同一条横行、纵行或斜线上。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/n-queens
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class SolveNQueens {
    public static void main(String[] args) {
        List<List<String>> lists = new SolveNQueens().solveNQueens(4);
        for (List<String> list : lists) {
            for (String s : list) {
                System.out.print(s);
            }
            System.out.println();
        }
    }

    public List<List<String>> solveNQueens(int n) {
        char[][] chars = init(n);
        List<List<String>> results = new ArrayList<>();
        solve(n, results, chars, 0);
        return results;
    }


    private void solve(int n, List<List<String>> results, char[][] chars, int row) {
        if (n == row) {
            results.add(construct(chars));
            return;
        }
        for (int col = 0; col < n; col++) {//对行元素进行遍历，放在皇后的位置
            if (isValid(col, row, chars)) {
                chars[row][col] = 'Q';
                solve(n, results, chars, row + 1);//下一行，继续放置皇后
                chars[row][col] = '.';
            }
        }
    }

    private char[][] init(int n) {
        char[][] chars = new char[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                chars[i][j] = '.';
            }
        }
        return chars;
    }

    private boolean isValid(int col, int row, char[][] chars) {
        //列判断
        for (int i = 0; i <= row; i++) {
            if (chars[i][col] == 'Q') {
                return false;
            }
        }
        //判断对角线，斜率大于0
        int i = row;
        int j = col;
        while (i >= 0 && j < chars[0].length) {
            if (chars[i][j] == 'Q') {
                return false;
            }
            i--;
            j++;
        }

        //判断对角线，斜率小于0
        int l = row;
        int m = col;
        while (l >= 0 && m >= 0) {
            if (chars[l][m] == 'Q') {
                return false;
            }
            l--;
            m--;
        }
        return true;
    }

    private List<String> construct(char[][] chars) {
        int length = chars[0].length;
        List<String> list = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            String str = "";
            for (int j = 0; j < length; j++) {
                str += chars[i][j];
            }
            list.add(str);
        }
        return list;
    }


}
